home *** CD-ROM | disk | FTP | other *** search
/ PC go! 2018 July / PCgo 07-2018 CD-ROM Germany.iso / nw.pak / Unnamed File 004923.txt < prev    next >
Encoding:
Text File  |  2015-07-29  |  9.2 KB  |  290 lines

  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4.  
  5. // This module implements WebView (<webview>) as a custom element that wraps a
  6. // BrowserPlugin object element. The object element is hidden within
  7. // the shadow DOM of the WebView element.
  8.  
  9. var DocumentNatives = requireNative('document_natives');
  10. var GuestView = require('guestView').GuestView;
  11. var GuestViewContainer = require('guestViewContainer').GuestViewContainer;
  12. var WebViewConstants = require('webViewConstants').WebViewConstants;
  13. var WebViewEvents = require('webViewEvents').WebViewEvents;
  14. var WebViewInternal = require('webViewInternal').WebViewInternal;
  15.  
  16. // Represents the internal state of <webview>.
  17. function WebViewImpl(webviewElement) {
  18.   GuestViewContainer.call(this, webviewElement, 'webview');
  19.  
  20.   this.beforeFirstNavigation = true;
  21.  
  22.   this.setupWebViewAttributes();
  23.   this.setupElementProperties();
  24.  
  25.   // on* Event handlers.
  26.   this.on = {};
  27.   new WebViewEvents(this, this.viewInstanceId);
  28. }
  29.  
  30. WebViewImpl.prototype.__proto__ = GuestViewContainer.prototype;
  31.  
  32. WebViewImpl.VIEW_TYPE = 'WebView';
  33.  
  34. // Add extra functionality to |this.element|.
  35. WebViewImpl.setupElement = function(proto) {
  36.   // Public-facing API methods.
  37.   var apiMethods = WebViewImpl.getApiMethods();
  38.  
  39.   // Add the experimental API methods, if available.
  40.   var experimentalApiMethods =
  41.       WebViewImpl.maybeGetExperimentalApiMethods();
  42.   apiMethods = $Array.concat(apiMethods, experimentalApiMethods);
  43.  
  44.   // Create default implementations for undefined API methods.
  45.   var createDefaultApiMethod = function(m) {
  46.     return function(var_args) {
  47.       if (!this.guest.getId()) {
  48.         return false;
  49.       }
  50.       var args = $Array.concat([this.guest.getId()], $Array.slice(arguments));
  51.       $Function.apply(WebViewInternal[m], null, args);
  52.       return true;
  53.     };
  54.   };
  55.   for (var i = 0; i != apiMethods.length; ++i) {
  56.     if (WebViewImpl.prototype[apiMethods[i]] == undefined) {
  57.       WebViewImpl.prototype[apiMethods[i]] =
  58.           createDefaultApiMethod(apiMethods[i]);
  59.     }
  60.   }
  61.  
  62.   // Forward proto.foo* method calls to WebViewImpl.foo*.
  63.   GuestViewContainer.forwardApiMethods(proto, apiMethods);
  64. };
  65.  
  66. // Initiates navigation once the <webview> element is attached to the DOM.
  67. WebViewImpl.prototype.onElementAttached = function() {
  68.   if (this.element.reserveOnDetach) {
  69.     return;
  70.   }
  71.   this.attributes[WebViewConstants.ATTRIBUTE_SRC].parse();
  72. };
  73.  
  74. // Resets some state upon detaching <webview> element from the DOM.
  75. WebViewImpl.prototype.onElementDetached = function() {
  76.   if (this.element.reserveOnDetach)
  77.     return;
  78.   this.guest.destroy();
  79.   this.beforeFirstNavigation = true;
  80.   this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].validPartitionId =
  81.       true;
  82.   this.internalInstanceId = 0;
  83. };
  84.  
  85. // Sets the <webview>.request property.
  86. WebViewImpl.prototype.setRequestPropertyOnWebViewElement = function(request) {
  87.   Object.defineProperty(
  88.       this.element,
  89.       'request',
  90.       {
  91.         value: request,
  92.         enumerable: true
  93.       }
  94.   );
  95. };
  96.  
  97. WebViewImpl.prototype.setupElementProperties = function() {
  98.   // We cannot use {writable: true} property descriptor because we want a
  99.   // dynamic getter value.
  100.   Object.defineProperty(this.element, 'contentWindow', {
  101.     get: function() {
  102.       if (this.guest.getContentWindow()) {
  103.         return this.guest.getContentWindow();
  104.       }
  105.       window.console.error(
  106.           WebViewConstants.ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE);
  107.     }.bind(this),
  108.     // No setter.
  109.     enumerable: true
  110.   });
  111.  
  112.   Object.defineProperty(this.element, 'reserveOnDetach', {
  113.     value: false,
  114.     writable: true,
  115.     enumerable: true,
  116.     configurable: true
  117.   });
  118. };
  119.  
  120. // This observer monitors mutations to attributes of the <webview>.
  121. WebViewImpl.prototype.handleAttributeMutation = function(
  122.     attributeName, oldValue, newValue) {
  123.   if (!this.attributes[attributeName] ||
  124.       this.attributes[attributeName].ignoreMutation) {
  125.     return;
  126.   }
  127.  
  128.   // Let the changed attribute handle its own mutation;
  129.   this.attributes[attributeName].handleMutation(oldValue, newValue);
  130. };
  131.  
  132. WebViewImpl.prototype.onSizeChanged = function(webViewEvent) {
  133.   var newWidth = webViewEvent.newWidth;
  134.   var newHeight = webViewEvent.newHeight;
  135.  
  136.   var element = this.element;
  137.  
  138.   var width = element.offsetWidth;
  139.   var height = element.offsetHeight;
  140.  
  141.   // Check the current bounds to make sure we do not resize <webview>
  142.   // outside of current constraints.
  143.   var maxWidth = this.attributes[
  144.     WebViewConstants.ATTRIBUTE_MAXWIDTH].getValue() || width;
  145.   var minWidth = this.attributes[
  146.     WebViewConstants.ATTRIBUTE_MINWIDTH].getValue() || width;
  147.   var maxHeight = this.attributes[
  148.     WebViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() || height;
  149.   var minHeight = this.attributes[
  150.     WebViewConstants.ATTRIBUTE_MINHEIGHT].getValue() || height;
  151.  
  152.   minWidth = Math.min(minWidth, maxWidth);
  153.   minHeight = Math.min(minHeight, maxHeight);
  154.  
  155.   if (!this.attributes[WebViewConstants.ATTRIBUTE_AUTOSIZE].getValue() ||
  156.       (newWidth >= minWidth &&
  157.       newWidth <= maxWidth &&
  158.       newHeight >= minHeight &&
  159.       newHeight <= maxHeight)) {
  160.     element.style.width = newWidth + 'px';
  161.     element.style.height = newHeight + 'px';
  162.     // Only fire the DOM event if the size of the <webview> has actually
  163.     // changed.
  164.     this.dispatchEvent(webViewEvent);
  165.   }
  166. };
  167.  
  168. WebViewImpl.prototype.createGuest = function() {
  169.   var params = {
  170.     'storagePartitionId': this.attributes[
  171.       WebViewConstants.ATTRIBUTE_PARTITION].getValue()
  172.   };
  173.  
  174.   this.guest.create(params, function() {
  175.     this.attachWindow();
  176.   }.bind(this));
  177. };
  178.  
  179. WebViewImpl.prototype.onFrameNameChanged = function(name) {
  180.   name = name || '';
  181.   if (name === '') {
  182.     this.element.removeAttribute(WebViewConstants.ATTRIBUTE_NAME);
  183.   } else {
  184.     this.attributes[WebViewConstants.ATTRIBUTE_NAME].setValue(name);
  185.   }
  186. };
  187.  
  188. WebViewImpl.prototype.dispatchEvent = function(webViewEvent) {
  189.   return this.element.dispatchEvent(webViewEvent);
  190. };
  191.  
  192. // Adds an 'on<event>' property on the webview, which can be used to set/unset
  193. // an event handler.
  194. WebViewImpl.prototype.setupEventProperty = function(eventName) {
  195.   var propertyName = 'on' + eventName.toLowerCase();
  196.   Object.defineProperty(this.element, propertyName, {
  197.     get: function() {
  198.       return this.on[propertyName];
  199.     }.bind(this),
  200.     set: function(value) {
  201.       if (this.on[propertyName])
  202.         this.element.removeEventListener(eventName, this.on[propertyName]);
  203.       this.on[propertyName] = value;
  204.       if (value)
  205.         this.element.addEventListener(eventName, value);
  206.     }.bind(this),
  207.     enumerable: true
  208.   });
  209. };
  210.  
  211. // Updates state upon loadcommit.
  212. WebViewImpl.prototype.onLoadCommit = function(
  213.     baseUrlForDataUrl, currentEntryIndex, entryCount,
  214.     processId, url, isTopLevel) {
  215.   this.baseUrlForDataUrl = baseUrlForDataUrl;
  216.   this.currentEntryIndex = currentEntryIndex;
  217.   this.entryCount = entryCount;
  218.   this.processId = processId;
  219.   var oldValue = this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue();
  220.   var newValue = url;
  221.   if (isTopLevel && (oldValue != newValue)) {
  222.     // Touching the src attribute triggers a navigation. To avoid
  223.     // triggering a page reload on every guest-initiated navigation,
  224.     // we do not handle this mutation.
  225.     this.attributes[WebViewConstants.ATTRIBUTE_SRC].setValueIgnoreMutation(
  226.         newValue);
  227.   }
  228. };
  229.  
  230. WebViewImpl.prototype.onAttach = function(storagePartitionId) {
  231.   this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].setValue(
  232.       storagePartitionId);
  233. };
  234.  
  235. WebViewImpl.prototype.buildAttachParams = function() {
  236.   var params = { 'userAgentOverride': this.userAgentOverride };
  237.   for (var i in this.attributes) {
  238.     params[i] = this.attributes[i].getValue();
  239.   }
  240.   return params;
  241. };
  242.  
  243. WebViewImpl.prototype.attachWindow = function(opt_guestInstanceId) {
  244.   // If |opt_guestInstanceId| was provided, then a different existing guest is
  245.   // being attached to this webview, and the current one will get destroyed.
  246.   if (opt_guestInstanceId) {
  247.     if (this.guest.getId() == opt_guestInstanceId) {
  248.       return true;
  249.     }
  250.     this.guest.destroy();
  251.     this.guest = new GuestView('webview', opt_guestInstanceId);
  252.   }
  253.  
  254.   return GuestViewContainer.prototype.attachWindow.call(this);
  255. };
  256.  
  257. // Shared implementation of executeScript() and insertCSS().
  258. WebViewImpl.prototype.executeCode = function(func, args) {
  259.   if (!this.guest.getId()) {
  260.     window.console.error(WebViewConstants.ERROR_MSG_CANNOT_INJECT_SCRIPT);
  261.     return false;
  262.   }
  263.  
  264.   var webviewSrc = this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue();
  265.   if (this.baseUrlForDataUrl != '') {
  266.     webviewSrc = this.baseUrlForDataUrl;
  267.   }
  268.  
  269.   args = $Array.concat([this.guest.getId(), webviewSrc],
  270.                        $Array.slice(args));
  271.   $Function.apply(func, null, args);
  272.   return true;
  273. }
  274.  
  275. // Implemented when the ChromeWebView API is available.
  276. WebViewImpl.prototype.maybeGetChromeWebViewEvents = function() {};
  277.  
  278. // Implemented when the experimental WebView API is available.
  279. WebViewImpl.maybeGetExperimentalApiMethods = function() { return []; };
  280. WebViewImpl.prototype.setupExperimentalContextMenus = function() {};
  281. WebViewImpl.prototype.maybeSetupExperimentalChromeWebViewEvents =
  282.   function(request) {
  283.     return request;
  284. };
  285.  
  286. GuestViewContainer.registerElement(WebViewImpl);
  287.  
  288. // Exports.
  289. exports.WebViewImpl = WebViewImpl;
  290.